package com.itheima.server.service;

import cn.hutool.core.collection.CollUtil;
import com.itheima.dubbo.api.UserInfoApi;
import com.itheima.dubbo.api.mongo.MovementApi;

import com.itheima.dubbo.api.mongo.VisitorsApi;
import com.itheima.server.interceptor.UserHolder;
import com.tanhua.autoconfig.template.OssTemplate;
import com.tanhua.commons.utils.Constants;
import com.tanhua.model.domain.UserInfo;
import com.tanhua.model.mongo.Movement;
import com.tanhua.model.mongo.Visitors;
import com.tanhua.model.vo.MovementsVo;
import com.tanhua.model.vo.PageResult;
import com.tanhua.model.vo.VisitorsVo;
import io.jsonwebtoken.lang.Collections;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.Reference;
import org.bson.types.ObjectId;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class MovementsService {

    @Autowired
    private OssTemplate ossTemplate;

    @DubboReference
    private MovementApi movementApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @DubboReference
    private VisitorsApi visitorsApi;

    @Autowired
    private MqMessageService messageService;

    /**
     * 发布朋友圈
     * @param movement
     * @param imageContent
     */
    public void saveMovements(Movement movement, MultipartFile[] imageContent) throws IOException {
        //1. 把图片上传到阿里云，把图片的地址信息保存到集合中
        List<String> imageList = new ArrayList<>();
        if(imageContent!=null&&imageContent.length!=0){
            for (MultipartFile imageItem : imageContent) {
                String imageUrl = ossTemplate.upload(imageItem.getOriginalFilename(), imageItem.getInputStream());
                imageList.add(imageUrl);
            }
        }
        //2. 给movement设置朋友圈的图片路径,补全其他的相关的参数
        movement.setUserId(UserHolder.getId()); //当前发布人的id
        movement.setCreated(System.currentTimeMillis()); //发布的时间
        movement.setMedias(imageList); //图片的地址
        movement.setId(ObjectId.get());
        //3. 保存朋友圈
        movementApi.save(movement);

        //4.把朋友圈的消息发发送到mq
        messageService.sendAudiService(movement.getId().toString());

    }

    /**
     * 根据用户id查询当前用户的动态
     * @param page
     * @param pagesize
     * @param userId
     * @return
     */
    public PageResult findByUserId(Integer page, Integer pagesize, Long userId) {
        //1. 根据用户id查询当前用户的动态分页对象
        PageResult pageResult = movementApi.findByUserId(userId,page,pagesize);  //存储是Movement
        //2. 得到分页对象集合
        List<Movement> movementList = (List<Movement>) pageResult.getItems();
        //3.查询当前用户的信息对象
        UserInfo userInfo = userInfoApi.findById(userId);
        //4. 遍历朋友圈
        List<MovementsVo> voList = new ArrayList<>();
        for (Movement movement : movementList) {
            MovementsVo movementsVo = MovementsVo.init(userInfo, movement);
            isLikeOrLove(movement.getId().toString(),movementsVo);
            voList.add(movementsVo);
        }

        pageResult.setItems(voList);
        return pageResult; //最终pageresult存储的是MovementVo
    }

    /**
     * 作用：好友动态
     * @param page
     * @param pagesize
     * @return
     */
    public PageResult findFriendMovements(Integer page, Integer pagesize) {
        //1.获取当前的登陆者的id，查询得到分页对象 PageResult<Movement>
        Long userId = UserHolder.getId();
        PageResult pageResult = movementApi.findFriendMovements(page,pagesize,userId);
        //2.提取UserId
        List<Movement> movementList = (List<Movement>) pageResult.getItems();
        List<Long> userIds = CollUtil.getFieldValues(movementList, "userId", Long.class);
        //3. 批量查询UserInfo对象
        Map<Long, UserInfo> userInfoMap = userInfoApi.findByIds(userIds);
        List<MovementsVo> voList = new ArrayList<>();
        //4. 遍历movemList，构建MoveMentVo
        for (Movement movement : movementList) {
            UserInfo userInfo = userInfoMap.get(movement.getUserId());
            MovementsVo vo = MovementsVo.init(userInfo, movement);
            isLikeOrLove(movement.getId().toString(),vo);
            voList.add(vo);
        }
        pageResult.setItems(voList);
        return pageResult;
    }

    /**
     * 查询推荐的动态
     * @param page
     * @param pagesize
     * @return
     */
    public PageResult recommend(Integer page, Integer pagesize) {
        //1. 获取当前登陆者的用户id，然后从redis中取出推荐的动态数据
        Long userId = UserHolder.getId();
        String key = Constants.MOVEMENTS_RECOMMEND+userId;
        String redisData = redisTemplate.opsForValue().get(key);  // 16,17,18,19,20,21,22
        //2.判断redis中是否存在推荐的数据，如果没有随机生成pagesize条
        List<Movement> movementList = null;
        String[] pidA=null;
        if(StringUtils.isEmpty(redisData)){
            //如果redis的数据取出来是空数据，那么代表没有给该用户推荐朋友圈，我们则随机去生成朋友圈数据
            movementList = movementApi.randomMovements(pagesize);
        }else {
            //3.判断redis中是否存在推荐的数据，那么我们就根据pid去查询对应的movement
            String[] pidArray = redisData.split(",");  // 16,17,18,19,20,21,22
            pidA=pidArray;
            //4.判断开始查询的索引值是否超过了当前数组的长度，
            if((page-1)*pagesize>=pidArray.length){
                movementList = new ArrayList<>();
            }else{
                List<Long> pidList = Arrays.stream(pidArray)
                        .skip((page - 1) * pagesize)
                        .limit(pagesize)
                        .map(pid -> {
                            return Long.valueOf(pid);
                        })
                        .collect(Collectors.toList());
                movementList = movementApi.findByPids(pidList);
            }
        }
        //5. 提取所有的UserId
        List<Long> userIdList = CollUtil.getFieldValues(movementList, "userId", Long.class);
        //6. 批量查询userInfo
        Map<Long, UserInfo> userInfoMap = userInfoApi.findByIds(userIdList);

        //7. 遍历movementList构建vo对象
        List<MovementsVo> voList = new ArrayList<>();
        for (Movement movement : movementList) {
            UserInfo userInfo = userInfoMap.get(movement.getUserId());
            MovementsVo movementsVo = MovementsVo.init(userInfo, movement);
            isLikeOrLove(movement.getId().toString(),movementsVo);
            voList.add(movementsVo);
        }
        Integer counts= redisData==null?pagesize:pidA.length;
        //8. 最后封装pageREsult对象返回出去，pageResult存储的是MovementVo
        return new PageResult(page.longValue(),pagesize.longValue(),counts.longValue(),voList);
    }


    public void isLikeOrLove(String  movementId,MovementsVo vo){
        String likeKey = Constants.USER_LIKE_KEY+movementId+"_"+UserHolder.getId();   //USER_LIKE_SET_movementId_2
        String loveKey = Constants.MOVEMENT_LOVE_HASHKEY+movementId+"_"+UserHolder.getId();   //USER_LIKE_SET_movementId_2
        if(redisTemplate.hasKey(likeKey)){
            //如果redis中存在该键，则代表已经点赞
            vo.setHasLiked(1);
        }

        if(redisTemplate.hasKey(loveKey)){
            //如果redis中存在该键，则代表已经点赞
            vo.setHasLoved(1);
        }
    }



    /**
     *接口名称：单条动态
     */
    public MovementsVo findById(String movementId) {
        Movement movement = movementApi.findById(movementId);
        //2. 动态的发布人用户信息
        UserInfo userInfo = userInfoApi.findById(movement.getUserId());
        MovementsVo movementsVo = MovementsVo.init(userInfo, movement);
        return movementsVo;
    }


    /**
     *接口名称：谁看过我
     */
    public List<VisitorsVo> queryVisitorsList() {
        //1. 从redis中取出当前用户查看访客的时间记录
        String key = Constants.VISITORS_USER;
        String field = UserHolder.getId()+"";
        HashOperations<String, Object, Object> optionHash = redisTemplate.opsForHash();
        Long lastTime = optionHash.get(key, field)==null?null:Long.valueOf(optionHash.get(key,field).toString());

        //2. 得到访客记录  List<Visitors>
        List<Visitors> visitorsList = visitorsApi.queryVisitors(UserHolder.getId(),lastTime);

        //3. 从访客记录的集合中提取访客的visitorUserId
        List<Long> visitorIds = CollUtil.getFieldValues(visitorsList, "visitorUserId", Long.class);
        Map<Long, UserInfo> userInfoMap = userInfoApi.findByIds(visitorIds);

        //4. 遍历List集合，构建VisitorsVo
        List<VisitorsVo> voList = new ArrayList<>();
        visitorsList.forEach((visitors -> {
            UserInfo userInfo = userInfoMap.get(visitors.getVisitorUserId());
            VisitorsVo visitorsVo = VisitorsVo.init(userInfo, visitors);
            voList.add(visitorsVo);
        }));

        return voList;
    }
}